package com.mars.rabbitmq.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * @Author King
 * @create 2020/8/20 16:36
 */
public class KingServer {


    /**
     * 标识数字
     */
    private int flag = 0;
    /**
     * 缓冲区大小
     */
    private int BLOCK = 4096;
    /**
     * 接受数据缓冲区
     */
    private ByteBuffer sendbuffer = ByteBuffer.allocate(BLOCK);
    /**
     * 发送数据缓冲区
     */
    private ByteBuffer receivebuffer = ByteBuffer.allocate(BLOCK);

    private Selector selector;

    public KingServer(int port) throws IOException {

        ServerSocketChannel channel = ServerSocketChannel.open();

        channel.configureBlocking(false);

        ServerSocket serverSocket = channel.socket();

        serverSocket.bind(new InetSocketAddress(port));

        selector = Selector.open();

        channel.register(selector, SelectionKey.OP_ACCEPT);

    }

    public void listener() throws IOException {
        while (true) {
            selector.select();
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterable = selectionKeys.iterator();
            while (iterable.hasNext()) {
                SelectionKey key = iterable.next();
                iterable.remove();
                doHandler(key);
            }
        }
    }

    private void doHandler(SelectionKey selectionKey) throws IOException {
        ServerSocketChannel server = null;
        SocketChannel client = null;
        String receiveText;
        String sendText;
        int count = 0;
        if (selectionKey.isAcceptable()) {
            //事件--接收新的套字节连接
            server = (ServerSocketChannel) selectionKey.channel();
            client = server.accept();
            client.configureBlocking(false);
            client.register(selector, SelectionKey.OP_READ);
        } else if (selectionKey.isReadable()) {
            // 返回为之创建此键的通道。
            client = (SocketChannel) selectionKey.channel();
            //将缓冲区清空以备下次读取
            receivebuffer.clear();
            //读取服务器发送来的数据到缓冲区中
            count = client.read(receivebuffer);
            if (count > 0) {
                receiveText = new String(receivebuffer.array(), 0, count);
                System.out.println("服务器端接受客户端数据--:" + receiveText);
                client.register(selector, SelectionKey.OP_WRITE);
            }
        } else if (selectionKey.isWritable()) {
            //将缓冲区清空以备下次写入
            sendbuffer.clear();
            // 返回为之创建此键的通道。
            client = (SocketChannel) selectionKey.channel();
            sendText = "message from server--" + flag++;
            //向缓冲区中输入数据
            sendbuffer.put(sendText.getBytes());
            //将缓冲区各标志复位,因为向里面put了数据标志被改变要想从中读取数据发向服务器,就要复位
            sendbuffer.flip();
            //输出到通道
            client.write(sendbuffer);
            System.out.println("服务器端向客户端发送数据--：" + sendText);
            client.register(selector, SelectionKey.OP_READ);
        }
    }

    public static void main(String[] args) throws IOException {
        KingServer server = new KingServer(9898);
        server.listener();
    }


}
